Complex applications for embedded devices typically consist of multiple dependent software components. Each software component consists of one or multiple APIs (Application Programming Interfaces) which implement a specific functionality (or set of functionalities) of the application. The dependency between software components of an application means that some components need to call APIs from other components in order to implement their functionalities. Conventionally, when direct calls are made from one software component to an API from another software component, the address of the called API is hardcoded within the caller component during the compile/link process. This prevents switching between different code versions of a software component containing a called API because the start address of the called API will typically be different for each version.
In order to correct a defect or to improve a functionality of the application, it may only be necessary to update one of the software components. However, due to direct API calls made between the software components, any simple post-build update to a specific component requires a rebuild of the entire application in order to ensure hardcoded addresses of called APIs are also updated. Often the activities needed to rebuild and deploy the entire application are very complex, even though the needed updates are simple. There are also instances when the source code or object code for some components of the application may no longer be available, preventing a general rebuild.
In addition to the above, it is often desirable to be able to select which implementation of a polymorphic operation (method or function) to call at runtime, for example in order to change the behaviour of an application at run-time with no-downtime. C++ compilers typically implement dynamic dispatch with a data structure called a virtual table that defines the message to method mapping for a given class. Instances of that type will then store a pointer to this table as part of their instance data. However, because C++ does not support late binding, the virtual table in a C++ object cannot be modified at run-time or post build time, which limits the potential set of dispatch targets to a finite set chosen at compile-time.